!! Copyright (C) 2009,2010,2011,2012  Marco Restelli
!!
!! This file is part of:
!!   FEMilaro -- Finite Element Method toolkit
!!
!! FEMilaro is free software; you can redistribute it and/or modify it
!! under the terms of the GNU General Public License as published by
!! the Free Software Foundation; either version 3 of the License, or
!! (at your option) any later version.
!!
!! FEMilaro is distributed in the hope that it will be useful, but
!! WITHOUT ANY WARRANTY; without even the implied warranty of
!! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
!! General Public License for more details.
!!
!! You should have received a copy of the GNU General Public License
!! along with FEMilaro; If not, see <http://www.gnu.org/licenses/>.
!!
!! author: Marco Restelli                   <marco.restelli@gmail.com>

module mod_kinds
!General comments: define the working precision kind wp for reals. No
! definitions are provided for integer kinds since it is usually
! better to use the default kinds.
!-----------------------------------------------------------------------

!-----------------------------------------------------------------------

 use mod_messages, only: &
   mod_messages_initialized, &
   error,   &
   warning, &
   info

!-----------------------------------------------------------------------
 
 implicit none

!-----------------------------------------------------------------------

! Module interface

 public :: &
   mod_kinds_constructor, &
   mod_kinds_destructor,  &
   mod_kinds_initialized, &
   wp, wp_p, wp_r

 private

!-----------------------------------------------------------------------

! Module types and parameters

 ! public members

 !----------------------------------------------------------------------
 ! Select here the working precision wp
 !
 ! single precision
 !integer, parameter :: wp = selected_real_kind(6,35)
 !
 ! double precision
 integer, parameter :: wp = selected_real_kind(12,307)
 !
 ! quadruple precision
 !integer, parameter :: wp = selected_real_kind(30,307)
 !----------------------------------------------------------------------

! Module variables

 ! public members
 integer, parameter :: &
   wp_p = precision(1.0_wp), &
   wp_r = range(1.0_wp)
 logical, protected ::               &
   mod_kinds_initialized = .false.
 ! private members
 character(len=*), parameter :: &
   this_mod_name = 'mod_kinds'

!-----------------------------------------------------------------------

contains

!-----------------------------------------------------------------------

 subroutine mod_kinds_constructor()

  character(len=100) message(3)
  character(len=*), parameter :: &
    this_sub_name = 'constructor'

   !Consistency checks ---------------------------
   if( (mod_messages_initialized.eqv..false.) ) then
     call error(this_sub_name,this_mod_name, &
                'Not all the required modules are initialized.')
   endif
   if(mod_kinds_initialized.eqv..true.) then
     call warning(this_sub_name,this_mod_name, &
                  'Module is already initialized.')
   endif
   !----------------------------------------------

   write(message(1),'(A,I3)') 'working precision wp = ', wp
   write(message(2),'(A,I5)') 'precision = ', wp_p
   write(message(3),'(A,I5)') 'range = ', wp_r
   call info(this_sub_name,this_mod_name,message)

   mod_kinds_initialized = .true.
 end subroutine mod_kinds_constructor

!-----------------------------------------------------------------------
 
 subroutine mod_kinds_destructor()
  character(len=*), parameter :: &
    this_sub_name = 'destructor'
   
   !Consistency checks ---------------------------
   if(mod_kinds_initialized.eqv..false.) then
     call error(this_sub_name,this_mod_name, &
                'This module is not initialized.')
   endif
   !----------------------------------------------

   mod_kinds_initialized = .false.
 end subroutine mod_kinds_destructor

!-----------------------------------------------------------------------

end module mod_kinds

